From 4a9bf575bd24b2e24348c65d9fbbf9c81a73cb35 Mon Sep 17 00:00:00 2001 From: Sebastien Castiel Date: Tue, 30 Jan 2024 16:36:29 -0500 Subject: Create expense from receipt (#69) * Create expense from receipt * Add modal * Update README --- .../expenses/create-from-receipt-button-actions.ts | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/app/groups/[groupId]/expenses/create-from-receipt-button-actions.ts (limited to 'src/app/groups/[groupId]/expenses/create-from-receipt-button-actions.ts') diff --git a/src/app/groups/[groupId]/expenses/create-from-receipt-button-actions.ts b/src/app/groups/[groupId]/expenses/create-from-receipt-button-actions.ts new file mode 100644 index 0000000..1714f82 --- /dev/null +++ b/src/app/groups/[groupId]/expenses/create-from-receipt-button-actions.ts @@ -0,0 +1,48 @@ +'use server' +import { getCategories } from '@/lib/api' +import { env } from '@/lib/env' +import OpenAI from 'openai' + +const openai = new OpenAI({ apiKey: env.OPENAI_API_KEY }) + +export async function extractExpenseInformationFromImage(imageUrl: string) { + 'use server' + const categories = await getCategories() + + const body = { + model: 'gpt-4-vision-preview', + messages: [ + { + role: 'user', + content: [ + { + type: 'text', + text: ` + This image contains a receipt. + Read the total amount and store it as a non-formatted number without any other text or currency. + Then guess the category for this receipt amoung the following categories and store its ID: ${categories.map( + ({ id, grouping, name }) => `"${grouping}/${name}" (ID: ${id})`, + )}. + Guess the expense’s date and store it as yyyy-mm-dd. + Guess a title for the expense. + Return the amount, the category, the date and the title with just a comma between them, without anything else.`, + }, + ], + }, + { + role: 'user', + content: [{ type: 'image_url', image_url: { url: imageUrl } }], + }, + ], + } + const completion = await openai.chat.completions.create(body as any) + + const [amountString, categoryId, date, title] = completion.choices + .at(0) + ?.message.content?.split(',') ?? [null, null, null, null] + return { amount: Number(amountString), categoryId, date, title } +} + +export type ReceiptExtractedInfo = Awaited< + ReturnType +> -- cgit v1.3